home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1994 November / Cd Ware (Nro. 2) - Epimundo.iso / OS2 / PC2_170.ZIP / SOURCE.ZIP / Source / Thread.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-01  |  50.5 KB  |  821 lines

  1. /***********************************************************************\
  2.  *                              Thread.c                               *
  3.  *                 Copyright (C) by Stangl Roman, 1994                 *
  4.  * This Code may be freely distributed, provided the Copyright isn't   *
  5.  * removed, under the conditions indicated in the documentation.       *
  6.  *                                                                     *
  7.  * Thread.c     PC/2's object window working thread.                   *
  8.  *                                                                     *
  9. \***********************************************************************/
  10.  
  11. static char RCSID[]="@(#) $Header: Thread.c Version 1.70 06,1994 $ (LBL)";
  12.  
  13. #define         _FILE_  "PC/2 - Thread.c V1.70"
  14.  
  15. #include        "PC2.h"                 /* User include files */
  16. #include        "Error.h"
  17.  
  18. typedef struct  _ColorWindow    COLORWINDOW;
  19.  
  20. struct  _ColorWindow
  21. {
  22. ULONG   ulBackgroundRGB;                /* RGB background color of window drawn on overview window */
  23. ULONG   ulForegroundRGB;                /* RGB foreground color of window text */
  24. };
  25.  
  26. HWND    hwndThread;                     /* PC/2's working thread window handle */
  27. HPS     hpsClient;                      /* PC/2's client area presentation space */
  28. SWP     swpApplications[128];           /* Window position of all enumerated applications
  29.                                            except Window List, PC/2 and optionally Desktop */
  30. ULONG   ulApplicationsCount;            /* Counter of last filled entry within array
  31.                                            swpApplications */
  32.  
  33.                                         /* PC/2's working thread */
  34. void _Optlink   PC2_Thread(void *ThreadArg)
  35. {
  36. HAB     habThread;
  37. HMQ     hmqThread;
  38. QMSG    qmsgThread;
  39.  
  40. while(TRUE)
  41. {
  42.                                         /* Initialize anchor block and message queue */
  43.     if(WinStartUp(&habThread, &hmqThread)==FALSE)
  44.         {
  45.         USR_ERR("Can't create a object window Thread - exiting...", (HWND)NULL, (HWND)NULL);
  46.                                         /* On error shut down PC/2 */
  47.         WinPostMsg(hwndClient, WM_QUIT, NULL, NULL);
  48.         break;
  49.         }
  50.     if(!WinRegisterClass(               /* Register window class */
  51.         habThread,                      /* Handle of anchor block */
  52.         (PSZ)PC2_CLASSNAME_THREAD,      /* Window class name */
  53.         (PFNWP)PC2_ThreadWindowProc,    /* Address of window procedure */
  54.         CS_SIZEREDRAW | CS_SAVEBITS,
  55.         0))                             /* Extra window words */
  56.         {
  57.         GEN_ERR(habThread, (HWND)NULL, (HWND)NULL);
  58.                                         /* On error shut down PC/2 */
  59.         WinPostMsg(hwndClient, WM_QUIT, NULL, NULL);
  60.         break;
  61.         }
  62.     hwndThread=WinCreateWindow(
  63.         HWND_OBJECT,                    /* Parent window */
  64.         PC2_CLASSNAME_THREAD,           /* Window class */
  65.         NULL,                           /* Window text */
  66.         0,                              /* Window style */
  67.                                         /* Windos position & size */
  68.         0, 0, 0, 0,
  69.         HWND_OBJECT,                    /* Owner window */
  70.         HWND_BOTTOM,                    /* Sibling window */
  71.         ID_PC2MAINWINDOW,               /* Window ID */
  72.         NULL,                           /* Control data */
  73.         NULL);                          /* Presentation parameters */
  74.                                         /* Create a standard window */
  75. /*                                                                                      *\
  76.  * Now setup working thread's required data.                                            *
  77. \*                                                                                      */
  78.                                         /* Get presentation space for PC/2's client window */
  79.     hpsClient=WinGetPS(hwndClient);
  80.                                         /* Set default font to 8.Helv */
  81.     WinSetPresParam(hwndClient, PP_FONTNAMESIZE, sizeof("8.Helv"), "8.Helv");
  82.     GpiCreateLogColorTable(hpsClient,   /* Change color table into RGB mode */
  83.         0L,                             /* Options */
  84.         LCOLF_RGB,                      /* Set color table into RGB mode */
  85.         0L, 0L, NULL);                  /* Starting, ending item, table */
  86.                                         /* Post message to query Desktop's/PM window handle */
  87.     WinPostMsg(hwndThread, WM_SETDESKTOPHANDLE, NULL, NULL);
  88.                                         /* Start working thread task loop */
  89.     WinPostMsg(hwndThread, WM_WORKINGTHREAD, NULL, NULL);
  90. /*                                                                                      *\
  91.  * Here we loop dispatching the messages...                                             *
  92. \*                                                                                      */
  93.     while(WinGetMsg(habThread, &qmsgThread, 0, 0, 0))
  94.                                             /* Dispatch messages to window procedure */
  95.         WinDispatchMsg(habThread, &qmsgThread);
  96.     break;
  97. }
  98. WinReleasePS(hpsClient);                /* Release presentation space */
  99. WinDestroyWindow(hwndThread);           /* Close window */
  100. WinDestroyMsgQueue(hmqThread);
  101. WinTerminate(habThread);
  102. _endthread();                           /* Terminate C thread code */
  103. DosExit(EXIT_THREAD, 0UL);              /* Terminate thread */
  104. }
  105.  
  106. /*--------------------------------------------------------------------------------------*\
  107.  * This procedure is the PC/2 working thread window procedure (is an object window).    *
  108. \*--------------------------------------------------------------------------------------*/
  109. MRESULT EXPENTRY PC2_ThreadWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  110. {
  111. static ULONG    ulRepaintRequest=0;     /* Count overview window repaint requests */
  112.  
  113. switch(msg)
  114. {
  115. /*                                                                                      *\
  116.  * Syntax: WM_REPAINT, NULL, NULL                                                       *
  117. \*                                                                                      */
  118. case WM_REPAINT:
  119. /*                                                                                      *\
  120.  * This message is send by any function that thinks the overview window needs to be     *
  121.  * redrawn. The variable ulRepaintRequest is used to stack repaint request reducing     *
  122.  * unnecessary redrawing.                                                               *
  123.  * Ref.:                                                                                *
  124.  *          none                                                                        *
  125. \*                                                                                      */
  126.     ulRepaintRequest++;                 /* Register repaint request */
  127.     break;
  128.  
  129. /*                                                                                      *\
  130.  * Syntax: WM_WORKINGTHREAD, NULL, NULL                                                 *
  131. \*                                                                                      */
  132. case WM_WORKINGTHREAD:
  133. /*                                                                                      *\
  134.  * This message is posted from the working thread to itself to permanently do a loop    *
  135.  * where pending tasks can be performed.                                                *
  136.  * Ref.:                                                                                *
  137.  *          ulRepaintRequest                                                            *
  138. \*                                                                                      */
  139.                                         /* Get current windows on PM */
  140.     WinSendMsg(hwnd, WM_SETUPSIZEPOSITION, NULL, NULL);
  141.                                         /* Test if some window positions have changed or
  142.                                            must be changed. If necessary move the windows */
  143.     WinSendMsg(hwnd, WM_DESKTOPMOVE, MPFROMLONG(0), MPFROMLONG(0));
  144.     if(ulRepaintRequest)                /* If overview window should be redrawn */
  145.         {                               /* Repaint overview window and reset repaint request counter */
  146.         WinSendMsg(hwnd, WM_PAINT, NULL, NULL);
  147.         ulRepaintRequest=0;
  148.         }
  149.     DosSleep(200);                      /* Give up some CPU timeslice */
  150.                                         /* Post message to query Desktop's/PM window handle */
  151.     WinPostMsg(hwnd, WM_SETDESKTOPHANDLE, NULL, NULL);
  152.                                         /* Do loop to perform pending tasks */
  153.     WinPostMsg(hwnd, WM_WORKINGTHREAD, NULL, NULL);
  154.     break;
  155.  
  156. /*                                                                                      *\
  157.  * Syntax: WM_PAINT, NULL, NULL                                                         *
  158. \*                                                                                      */
  159. case WM_PAINT:
  160. /*                                                                                      *\
  161.  * This message is send by PC/2's client window when a repaint is needed.               *
  162.  * Ref.:                                                                                *
  163.  *          none                                                                        *
  164. \*                                                                                      */
  165.     {
  166.     RECTL       rcClient;               /* Rectangle to redraw */
  167.     LONG        lX, lY;                 /* Position (x|y) on client area */
  168.     LONG        lXSize, lYSize;         /* Length on client area */
  169.     SWP         swpWindow;              /* Any window to be drawn on overview window */
  170.     ULONG       ulWindowIndex;          /* Index in Windows.wdWindow[] */
  171.                                         /* RGB colors available to draw winwdows */
  172.     COLORWINDOW ColorWindow[]={ {RGB_BLACK,  RGB_WHITE}, {RGB_BLUE,  RGB_WHITE}, {RGB_GREEN, RGB_BLACK},
  173.                                 {RGB_CYAN,   RGB_BLACK}, {RGB_RED,   RGB_WHITE}, {RGB_PINK,  RGB_WHITE},
  174.                                 {RGB_YELLOW, RGB_BLACK} };
  175.  
  176.                                         /* Get the client area size */
  177.     WinQueryWindowPos(hwndClient, &HookParameters.swpPC2Client);
  178.                                         /* Set background to dialog background */
  179.     WinQueryWindowRect(hwndClient, &rcClient);
  180.     WinFillRect(hpsClient, &rcClient, WinQuerySysColor(HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0L));
  181.                                         /* Now get scale factor to scale virtual Desktop
  182.                                            to client area */
  183.     HookParameters.fScaleX=(float)(HookParameters.swpPC2Client.cx-1)/(3*HookParameters.DesktopSize.x);
  184.     HookParameters.fScaleY=(float)(HookParameters.swpPC2Client.cy)/(3*HookParameters.DesktopSize.y);
  185.                                         /* Get coordinates (0|0) origin */
  186.     HookParameters.ptlOrigin.x=(HookParameters.VirtualDesktopPos.x+HookParameters.DesktopSize.x)*HookParameters.fScaleX;
  187.     HookParameters.ptlOrigin.y=(HookParameters.VirtualDesktopPos.y+HookParameters.DesktopSize.y)*HookParameters.fScaleY;
  188.                                         /* Get size of one of the 3 Desktops that must fit into
  189.                                            the client area */
  190.     lXSize=HookParameters.swpPC2Client.cx/3;
  191.     lYSize=HookParameters.swpPC2Client.cy/3;
  192.     swpWindow.cx=lXSize-1;
  193.     swpWindow.cy=lYSize-1;
  194.     for(lX=0; lX<=2; lX++)              /* Draw all 9 Virtual Desktops */
  195.         for(lY=0; lY<=2;lY++)
  196.             {
  197.             swpWindow.x=lX*lXSize;
  198.             swpWindow.y=lY*lYSize;
  199.             DrawWindow(hpsClient, &swpWindow, WinQuerySysColor(HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0L),
  200.                 0, FALSE, NULL);
  201.             }
  202.                                         /* Draw physical Desktop window */
  203.     swpWindow.x=HookParameters.ptlOrigin.x;
  204.     swpWindow.y=HookParameters.ptlOrigin.y;
  205.     DrawWindow(hpsClient, &swpWindow, RGB_WHITE, RGB_BLACK, TRUE, "Display");
  206.                                         /* Now display the windows from topmost to bottommost */
  207.     for(ulWindowIndex=Windows.ulWindowLast;
  208.         ulWindowIndex!=(ULONG)-1 && Windows.ulWindowLast!=(ULONG)-1;
  209.         ulWindowIndex--)
  210.         {
  211.                                         /* Ignore invisible windows */
  212.         if(!(Windows.wdWindow[ulWindowIndex].ulStatus & VISIBLE)) continue;
  213.                                         /* Calculate and draw window */
  214.         swpWindow.x=HookParameters.ptlOrigin.x+
  215.             (float)Windows.wdWindow[ulWindowIndex].swpWindow.x*HookParameters.fScaleX;
  216.         swpWindow.y=HookParameters.ptlOrigin.y+
  217.             (float)Windows.wdWindow[ulWindowIndex].swpWindow.y*HookParameters.fScaleY;
  218.         swpWindow.cx=(float)Windows.wdWindow[ulWindowIndex].swpWindow.cx*HookParameters.fScaleX;
  219.         swpWindow.cy=(float)Windows.wdWindow[ulWindowIndex].swpWindow.cy*HookParameters.fScaleY;
  220.                                         /* Display Window List title or titlebar */
  221.         if(strlen(Windows.wdWindow[ulWindowIndex].ucWindowTitle))
  222.             DrawWindow(hpsClient, &swpWindow,
  223.                 ColorWindow[ulWindowIndex % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulBackgroundRGB,
  224.                 ColorWindow[ulWindowIndex % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulForegroundRGB,
  225.                 TRUE, Windows.wdWindow[ulWindowIndex].ucWindowTitle);
  226.         else
  227.             DrawWindow(hpsClient, &swpWindow,
  228.                 ColorWindow[ulWindowIndex % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulBackgroundRGB,
  229.                 ColorWindow[ulWindowIndex % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulForegroundRGB,
  230.                 TRUE, Windows.wdWindow[ulWindowIndex].ucPgmTitle);
  231.         }
  232.     }
  233.     break;
  234.  
  235. /*                                                                                      *\
  236.  * Syntax: WM_DESKTOPMOVE, LONG SlidingXFactor, LONG SlidingYFactor                     *
  237. \*                                                                                      */
  238. case WM_DESKTOPMOVE:
  239. /*                                                                                      *\
  240.  * The hook found that the pointer was over one of the border rows and/or columns of    *
  241.  * the physical Desktop or the user doubleclicked on a virtual Desktop on the overview  *
  242.  * window. The passed parameter mp1 contains the number of pixels to slide all windows  *
  243.  * on the virtual Desktop horizontally. We calculate if and where the physical Desktop  *
  244.  * must be moved, or ignore it, if we're allready at a border position of the virtual   *
  245.  * Desktop.                                                                             *
  246. \*                                                                                      */
  247.     {
  248.                                         /* Slide in x direction in pixels */
  249.     LONG        lSlidingXFactor=LONGFROMMP(mp1);
  250.                                         /* Slide in y direction in pixels */
  251.     LONG        lSlidingYFactor=LONGFROMMP(mp2);
  252.     ULONG       ulWindowIndex=0;        /* Index in WINDOWS structure */
  253.     BOOL        bChanged=FALSE;         /* TRUE is at least one window has been changed
  254.                                            (added, removed, moved, sized,...) */
  255.  
  256.     ulApplicationsCount=0;              /* Begin with first window */
  257.                                         /* From all windows select the ones we are
  258.                                            interested to move */
  259.     for( ; ulWindowIndex<=Windows.ulWindowLast; ulWindowIndex++)
  260.         {
  261.                                         /* Ignore known windows not being a movable frame window. */
  262.         if(!(Windows.wdWindow[ulWindowIndex].ulStatus & FRAMECLASS))
  263.             continue;
  264.                                         /* Preserve Window list */
  265.         if(!strcmp(Windows.wdWindow[ulWindowIndex].ucPgmTitle, HookParameters.ucWindowListName))
  266.             continue;
  267.                                         /* Preserve PC/2's window */
  268.         if((strstr(Windows.wdWindow[ulWindowIndex].ucWindowTitle, "PC/2")) ||
  269.             (strstr(Windows.wdWindow[ulWindowIndex].ucPgmTitle, "PC/2"))) continue;
  270.                                         /* Only move certain window */
  271.         Windows.wdWindow[ulWindowIndex].swpWindow.x+=lSlidingXFactor;
  272.         Windows.wdWindow[ulWindowIndex].swpWindow.y+=lSlidingYFactor;
  273.                                         /* Copy flags to prevent unnecessary update only because
  274.                                            some styles mismatch we can ignore safely */
  275.         swpApplications[ulApplicationsCount].fl=Windows.wdWindow[ulWindowIndex].swpWindow.fl;
  276.                                         /* Now compare current one if it changed */
  277.         if(memcmp(&swpApplications[ulApplicationsCount], &Windows.wdWindow[ulWindowIndex].swpWindow, sizeof(SWP)))
  278.             {
  279.             bChanged=TRUE;
  280.             memcpy(&swpApplications[ulApplicationsCount], &Windows.wdWindow[ulWindowIndex].swpWindow, sizeof(SWP));
  281.                                         /* Move window only if not marked non-movable. Such a window
  282.                                            appears on every Virtual Desktop but may change its position
  283.                                            relative to the lower left corner so we have to compare its
  284.                                            old and new position to update overview window correctly */
  285.             if(Windows.wdWindow[ulWindowIndex].SwpFlag & SWP_NOMOVE)
  286.                 swpApplications[ulApplicationsCount].fl=SWP_NOADJUST;
  287.             else
  288.                 swpApplications[ulApplicationsCount].fl=SWP_MOVE | SWP_NOADJUST;
  289.             }
  290.         ulApplicationsCount++;
  291.         }
  292.                                         /* Now move all windows */
  293.     if(lSlidingXFactor || lSlidingYFactor)
  294.         {
  295.         if(WinSetMultWindowPos(hab, swpApplications, ulApplicationsCount))
  296.             {
  297.             bChanged=TRUE;              /* If windows were successfully moved update overview window */
  298.                                         /* Adjust physical Desktop within virtual Desktop */
  299.             HookParameters.VirtualDesktopPos.x-=lSlidingXFactor;
  300.             HookParameters.VirtualDesktopPos.y-=lSlidingYFactor;
  301.             }
  302.         else
  303.                                         /* If windows weren't successfully moved retry */
  304.             WinPostMsg(hwnd, WM_DESKTOPMOVE, MPFROMLONG(lSlidingXFactor), MPFROMLONG(lSlidingYFactor));
  305.  
  306.         }
  307.                                         /* If windows changed, request repaint client area */
  308.     if(bChanged) WinPostMsg(hwnd, WM_REPAINT, NULL, NULL);
  309.     }
  310.     break;
  311.  
  312. /*                                                                                      *\
  313.  * Syntax: WM_SETDESKTOPHANDLE, NULL, NULL                                              *
  314. \*                                                                                      */
  315. case WM_SETDESKTOPHANDLE:
  316. /*                                                                                      *\
  317.  * Query the window handle of the Desktop windows and load them into PC2HOOK.DLL        *
  318.  * library. If the WPS is installed, we can obtain its handle by searching for a window *
  319.  * class of #37. Even if the WPS is installed, we can also obtain the the window handle *
  320.  * of the PM, which is also present, if the WPS isn't installed.                        *
  321.  * Ref.:                                                                                *
  322.  *          Windows ........... WINDOWS structure containing all windows control data   *
  323. \*                                                                                      */
  324.     {
  325.     UCHAR       ucClass[8];             /* Save class name here */
  326.     HWND        hwndWPS;                /* Save WPS window handle */
  327.     HWND        hwndDesktop;            /* Save PM window handle */
  328.     HENUM       henumWindows;           /* Enumerate windows */
  329.  
  330.                                         /* Get to bottommost window handle of the "Desktop" */
  331.     hwndDesktop=WinQueryWindow(HWND_DESKTOP, QW_BOTTOM);
  332.                                         /* Enumerate all windows at "Desktop" z-order */
  333.     henumWindows=WinBeginEnumWindows(hwndDesktop);
  334.     while(hwndWPS=WinGetNextWindow(henumWindows))
  335.         {
  336.                                         /* Now get the class name of that window handle */
  337.         WinQueryClassName(hwndWPS, sizeof(ucClass), (PCH)ucClass);
  338.                                         /* If we find the required "Desktop" window (it
  339.                                            has a class name of #37, which is reserved in the
  340.                                            Toolkit) set this value into the Hook DLL.
  341.                                            The "Desktop" is just a WC_CONTAINER class.
  342.                                            This class is owned by the WPS, so we found the
  343.                                            WPS' window handle */
  344.         if(!strcmp(ucClass, DESKTOP_CLASS)) break;
  345.         }
  346.     WinEndEnumWindows(henumWindows);    /* End enumeration */
  347. /*                                                                                      *\
  348.  * Now get the PM window handle for the case, that the WPS is not installed, or moved   *
  349.  * outwards of the display (by setting the move Desktop checkbox).                      *
  350. \*                                                                                      */
  351.                                         /* Without WPS installed we can only get the
  352.                                            "Desktop" window handle */
  353.     hwndDesktop=WinQueryDesktopWindow(hab, NULLHANDLE);
  354.                                         /* Inform DLL if Desktop windows handles have
  355.                                            changed */
  356.     if((hwndWPS!=HookParameters.hwndWPS) || (hwndDesktop!=HookParameters.hwndDesktop))
  357.         {
  358.         HookParameters.hwndWPS=hwndWPS;
  359.         HookParameters.hwndDesktop=hwndDesktop;
  360.         }
  361.     }
  362.     break;
  363.  
  364. /*                                                                                      *\
  365.  * Syntax: WM_SETUPSIZEPOSITION, NULL, NULL                                             *
  366. \*                                                                                      */
  367. case WM_SETUPSIZEPOSITION:
  368. /*                                                                                      *\
  369.  * This message is executed in a loop by the object window thread. At the end of this   *
  370.  * message the message is posted again, after sleeping a while, to perform the loop.    *
  371.  * All windows running in the system are queried and registered in the Windows control  *
  372.  * structure.                                                                           *
  373.  * The Window List is queried to find the Window List entries of the PM windows.        *
  374.  * Ref.:                                                                                *
  375.  *          Windows ........... WINDOWS structure containing all windows control data   *
  376. \*                                                                                      */
  377.     {
  378.     ULONG       ulWindowIndex;          /* Index in Windows.wdWindow[] */
  379.     HENUM       henumDesktop;           /* Window handle of WC_FRAME class Desktop */
  380.     HWND        hwndApplication;        /* Window handles of enumerated application */
  381.     ULONG       ulWindowListCount, ulWindowListIndex;
  382.     MENUDATA    *pMD;                   /* Pointer to MENUDATA structure of corresponding window */
  383.     PSWBLOCK    pSwBlock;               /* Pointer to window list */
  384.     BOOL        bFoundItem;             /* TRUE if hotkey was found */
  385.  
  386.                                         /* Query the number of entries in window list */
  387.     ulWindowListCount=WinQuerySwitchList(hab, NULL, 0);
  388.                                         /* Allocate space for window list */
  389.     pSwBlock=(PSWBLOCK)malloc(ulWindowListCount=(ulWindowListCount*sizeof(SWENTRY)+sizeof(HSWITCH)));
  390.                                         /* Enumerate window list to query how the Session title of a
  391.                                            frame window (using it's window handle) is spelled in the
  392.                                            Window list */
  393.     ulWindowListCount=WinQuerySwitchList(hab, pSwBlock, ulWindowListCount);
  394.     Windows.ulDesktop=(ULONG)-1;        /* Set to -1 if we don't find the Desktop's name */
  395.     Windows.ulWindowList=(ULONG)-1;     /* Set to -1 if we don't find the Window List's name */
  396.     ulWindowIndex=(ULONG)-1;            /* Begin with offset 0 in first iteration */
  397.                                         /* Enumerate all descendants of HWND_DESKTOP,
  398.                                            which are the frame windows seen on Desktop,
  399.                                            but not having necessarily the class WC_FRAME */
  400.     henumDesktop=WinBeginEnumWindows(HWND_DESKTOP);
  401.     while(hwndApplication=WinGetNextWindow(henumDesktop))
  402.         {
  403.         ulWindowIndex++;
  404.                                         /* Asume window visible */
  405.         Windows.wdWindow[ulWindowIndex].ulStatus|=VISIBLE;
  406.         Windows.wdWindow[ulWindowIndex].ulStatus|=FRAMECLASS;
  407.                                         /* Get window's size and position */
  408.         WinQueryWindowPos(hwndApplication, &Windows.wdWindow[ulWindowIndex].swpWindow);
  409.         if(Windows.wdWindow[ulWindowIndex].swpWindow.fl & SWP_HIDE)
  410.             Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  411.                                         /* Get window's class name */
  412.         WinQueryClassName(hwndApplication, CLASSNAMESIZE,
  413.             Windows.wdWindow[ulWindowIndex].ucClassName);
  414.                                         /* If it is an minimized icon text class window
  415.                                            treat it as an invisible one */
  416.         if(!strcmp(Windows.wdWindow[ulWindowIndex].ucClassName, "#32765"))
  417.             Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  418.                                         /* If it is a menu treat it as an invisible one and
  419.                                            not being a frame window */
  420.         if(!strcmp(Windows.wdWindow[ulWindowIndex].ucClassName, "#4"))
  421.             {
  422.             Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  423.             Windows.wdWindow[ulWindowIndex].ulStatus &= (~FRAMECLASS);
  424.             }
  425.                                         /* Get window's titlebar */
  426.         WinQueryWindowText(hwndApplication, MAXNAMEL+1,
  427.             Windows.wdWindow[ulWindowIndex].ucPgmTitle);
  428.                                         /* If we found the index of the Window List save it */
  429.         if(strstr(Windows.wdWindow[ulWindowIndex].ucPgmTitle, HookParameters.ucWindowListName))
  430.             {
  431.             Windows.ulWindowList=ulWindowIndex;
  432.             Windows.wdWindow[ulWindowIndex].ulStatus &= (~FRAMECLASS);
  433.             }
  434.                                         /* If we found the index of the Desktop save it */
  435.         if(strstr(Windows.wdWindow[ulWindowIndex].ucPgmTitle, HookParameters.ucDesktopName))
  436.             {
  437.             Windows.ulDesktop=ulWindowIndex;
  438.             if(!(HookParameters.ulStatusFlag & MOVEDESKTOP))
  439.                 Windows.wdWindow[ulWindowIndex].ulStatus &= (~FRAMECLASS);
  440.             }
  441.                                         /* If we found PC/2, or any of PC/2's dialogs save it */
  442.         if(hwndApplication==hwndFrame)
  443.             {
  444.             Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  445.                                         /* Keep overview window on top (the focus may be in a
  446.                                            window below */
  447.             if(HookParameters.ulStatusFlag & KEEPONTOP)
  448.                 WinSetWindowPos(hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
  449.             }
  450.         if(strstr(Windows.wdWindow[ulWindowIndex].ucPgmTitle, "PC/2"))
  451.             Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  452.                                         /* If we don't find an entry in the Window List set
  453.                                            it to default empty string */
  454.         strcpy(Windows.wdWindow[ulWindowIndex].ucWindowTitle, "");
  455.                                         /* If we don't find an entry set to 0 */
  456.         Windows.wdWindow[ulWindowIndex].hswitchWindow=0;
  457.         for(ulWindowListIndex=0; ulWindowListIndex<=ulWindowListCount; ulWindowListIndex++)
  458.             {                           /* If window handle of frame window and window handle in
  459.                                            window list equal, copy the name of the entry from the
  460.                                            window list */
  461.             if(pSwBlock->aswentry[ulWindowListIndex].swctl.hwnd==Windows.wdWindow[ulWindowIndex].swpWindow.hwnd)
  462.                 {
  463.                 strcpy(Windows.wdWindow[ulWindowIndex].ucWindowTitle,
  464.                     pSwBlock->aswentry[ulWindowListIndex].swctl.szSwtitle);
  465.                                         /* Get the switch handle */
  466.                 Windows.wdWindow[ulWindowIndex].hswitchWindow=pSwBlock->aswentry[ulWindowListIndex].hswitch;
  467.                 break;                  /* If found we need no further seek */
  468.                 }
  469.             }
  470.                                         /* Search if current window is contained in PC/2's
  471.                                            Popup-Menu */
  472.         bFoundItem=FALSE;
  473.         pMD=SearchTitle(pPopupMenu, &Windows.wdWindow[ulWindowIndex], &bFoundItem);
  474.         if(pMD!=NULL)
  475.                                         /* If found copy flag because we need to determine
  476.                                            if window should be moved on virtual Desktops
  477.                                            and how it should be restored when hotkeying to it */
  478.             {
  479.             Windows.wdWindow[ulWindowIndex].SwpFlag=pMD->SwpFlag;
  480.             memcpy(&Windows.wdWindow[ulWindowIndex].KeyData, &(pMD->KeyData), sizeof(KEYDATA));
  481.             if(pMD->SwpFlag & SWP_MOVEWINDOW)
  482.                 {  
  483.                 USHORT  usSwp;
  484.                                         /* If window was only invisible because of the movement
  485.                                            make it visible again */
  486.                 if(pMD->SwpFlag & SWP_MOVEWINDOWVISIBLE)
  487.                     usSwp=SWP_MOVE | SWP_SHOW | SWP_NOADJUST;
  488.                 else
  489.                     usSwp=SWP_MOVE | SWP_NOADJUST;
  490.                                         /* If this flag is set we found an application's window
  491.                                            the first time after invokation and we have to reposition
  492.                                            it and reset the flag */
  493.                 pMD->SwpFlag&=(~(SWP_MOVEWINDOW | SWP_MOVEWINDOWVISIBLE));
  494.                                         /* Now calculate window's position on Virtual Desktops and
  495.                                            move it to its absolute (relative to logical 0|0) position */
  496.                 WinSetWindowPos(Windows.wdWindow[ulWindowIndex].swpWindow.hwnd, HWND_TOP,
  497.                     pMD->InitXPos-HookParameters.VirtualDesktopPos.x,
  498.                     pMD->InitYPos-HookParameters.VirtualDesktopPos.y,
  499.                     0, 0, usSwp);
  500.                 }
  501.             }
  502.         else
  503.             {
  504.             Windows.wdWindow[ulWindowIndex].SwpFlag=0;
  505.             memset(&Windows.wdWindow[ulWindowIndex].KeyData, 0, sizeof(KEYDATA));
  506.             }
  507.         }
  508.     WinEndEnumWindows(henumDesktop);    /* End enumeration */
  509.     Windows.ulWindowLast=ulWindowIndex;
  510.     free(pSwBlock);
  511.     }
  512.     break;
  513.  
  514. /*                                                                                      *\
  515.  * Syntax: WM_BUTTON1DBLCLK, (LONG mp1), (LONG mp2)                                     *
  516. \*                                                                                      */
  517. case WM_BUTTON1DBLCLK:
  518. /*                                                                                      *\
  519.  * This message detected and passed from the PC/2 window procedure is used to switch    *
  520.  * between Virtual Desktops.                                                            *
  521.  * Ref.:                                                                                *
  522.  *          Windows ........... WINDOWS structure containing all windows control data   *
  523. \*                                                                                      */
  524.     {
  525.     LONG        lClickX, lClickY;       /* Pointer position during click */
  526.     LONG        lSlidingXFactor;        /* Slide in x direction in pixels */
  527.     LONG        lSlidingYFactor;        /* Slide in y direction in pixels */
  528.  
  529.                                         /* Get the virtual Desktop the user doubleclicked on */
  530.     lClickX=-HookParameters.DesktopSize.x;
  531.     lClickY=-HookParameters.DesktopSize.y;
  532.     lClickX+=((LONG)(SHORT1FROMMP(mp1)))/(HookParameters.swpPC2Client.cx/3)*HookParameters.DesktopSize.x;
  533.     lClickY+=((LONG)(SHORT2FROMMP(mp1)))/(HookParameters.swpPC2Client.cy/3)*HookParameters.DesktopSize.y;
  534.                                         /* The right and top borders are the limit (necessary because
  535.                                            the frame rectrangle is sized pointwise and the virtual Desktops
  536.                                            drawn are sized every 3 points leaving 0 to 2 points outside.
  537.                                            Can be fixed by allowing the frame also sized only every 3
  538.                                            points, but I first must find out how to. */
  539.     if(lClickX>HookParameters.VirtualDesktopMax.x) lClickX=HookParameters.VirtualDesktopMax.x;
  540.     if(lClickY>HookParameters.VirtualDesktopMax.y) lClickY=HookParameters.VirtualDesktopMax.y;
  541.                                         /* Calculate Desktop move in pixel */
  542.     lSlidingXFactor=HookParameters.VirtualDesktopPos.x-lClickX;
  543.     lSlidingYFactor=HookParameters.VirtualDesktopPos.y-lClickY;
  544.     if(lSlidingXFactor || lSlidingYFactor)
  545.                                         /* Now move the windows */
  546.         WinPostMsg(hwndThread, WM_DESKTOPMOVE, MPFROMLONG(lSlidingXFactor), MPFROMLONG(lSlidingYFactor));
  547.     }
  548.     break;
  549.  
  550. /*                                                                                      *\
  551.  * Syntax: WM_HOTKEY, (USHORT usFlags, USHORT usCh), ULONG ulKeyDataIndex               *
  552.  *                                                                                      *
  553. \*                                                                                      */
  554. case WM_HOTKEY:
  555. /*                                                                                      *\
  556.  * WM_HOTKEY is a WM_CHAR message, passed when a hotkey was detected in PC2Hook.DLL.    *
  557.  * The key passed from the input hook is flaged as used. Either the running program     *
  558.  * corresponding to the hotkey is switched into the foreground, or if it is not already *
  559.  * running it is started.                                                               *
  560.  * Ref.:                                                                                *
  561.  *          Windows ........... WINDOWS structure containing all windows control data   *
  562. \*                                                                                      */
  563.     {
  564.                                         /* Get key code */
  565.     USHORT      usFlags=SHORT1FROMMP(mp1);
  566.                                         /* Get ASCII key value */
  567.     USHORT      usCh=SHORT2FROMMP(mp1);
  568.                                         /* Index in KeyData of HotKey found */
  569.     ULONG       ulKeyDataIndex=LONGFROMMP(mp2);
  570.     POINTL      VirtualDesktopPos;      /* Copy structure from HookParameters */
  571.     ULONG       ulWindowIndex;          /* Index in Windows.wdWindow[] */
  572.     POINTL      HotKeyWindow;           /* Position of the window the Hotkey is defined for
  573.                                            in coordinates relative to logical (0|0) point */
  574.     LONG        lSlidingXFactor=0;      /* Slide in x direction in pixels */
  575.     LONG        lSlidingYFactor=0;      /* Slide in y direction in pixels */
  576.     LONG        lDiff;
  577.     USHORT      usfl;                   /* Flags for WinSetWindowPos() */
  578.  
  579.     VirtualDesktopPos=HookParameters.VirtualDesktopPos;
  580.                                         /* Find match between actual hotkey pressed and
  581.                                            any (available) window this hotkey is defined for */
  582.     for(ulWindowIndex=0; ulWindowIndex<=Windows.ulWindowLast; ulWindowIndex++)
  583.         {
  584.         if((Windows.wdWindow[ulWindowIndex].KeyData.usFlags==usFlags) &&
  585.             (Windows.wdWindow[ulWindowIndex].KeyData.usCh==usCh))
  586.             break;
  587.         }
  588.                                         /* Only do something when a window for a hotkey
  589.                                            is available */
  590.     if(ulWindowIndex<=Windows.ulWindowLast)
  591.         {                               /* The coordinates in the WINDOWS structure are relative to
  592.                                            PM, which is, if the Virtual Desktop is enabled, relative
  593.                                            to the logical (0|0) point (which is the lower left position
  594.                                            of the Display in the overview window.
  595.                                            To get the position relative to logical (0|0) get the winow's
  596.                                            position on PM and add the logical position of PM relative to
  597.                                            logical (0|0). Compare with the middle of the hotkeyed window. */
  598.         HotKeyWindow.x=HookParameters.VirtualDesktopPos.x+
  599.             Windows.wdWindow[ulWindowIndex].swpWindow.x+(Windows.wdWindow[ulWindowIndex].swpWindow.cx>>1);
  600.         HotKeyWindow.y=HookParameters.VirtualDesktopPos.y+
  601.             Windows.wdWindow[ulWindowIndex].swpWindow.y+(Windows.wdWindow[ulWindowIndex].swpWindow.cy>>1);
  602.                                         /* Move physical Desktop right, but not over the
  603.                                            right border of the virtual Desktop until
  604.                                            the hotkeyed window's horizontal position comes
  605.                                            onto the Desktop */
  606.         while(HotKeyWindow.x>(VirtualDesktopPos.x+HookParameters.SlidingXFactor))
  607.             {                           /* Move physical Desktop right one additional unit,
  608.                                            can also be seen to move all windows in virtual
  609.                                            Desktop left one additional unit */
  610.             lSlidingXFactor-=HookParameters.SlidingXFactor;
  611.             VirtualDesktopPos.x+=HookParameters.SlidingXFactor;
  612.             lDiff=VirtualDesktopPos.x-HookParameters.VirtualDesktopMax.x;
  613.             if(lDiff>0)                 /* Correct if we moved out of the physical Desktop */
  614.                 {
  615.                 lSlidingXFactor+=lDiff;
  616.                 break;                  /* We can't move further */
  617.                 }
  618.             }
  619.                                         /* Do the same left */
  620.         while(HotKeyWindow.x<VirtualDesktopPos.x)
  621.             {                           /* Move physical Desktop left one additional unit */
  622.             lSlidingXFactor+=HookParameters.SlidingXFactor;
  623.             VirtualDesktopPos.x-=HookParameters.SlidingXFactor;
  624.             lDiff=VirtualDesktopPos.x-HookParameters.VirtualDesktopMin.x;
  625.             if(lDiff<0)                 /* Correct if we moved out of the physical Desktop */
  626.                 {
  627.                 lSlidingXFactor+=lDiff;
  628.                 break;                  /* We can't move further */
  629.                 }
  630.             }
  631.                                         /* Move physical Desktop up, but not over the
  632.                                            top border of the virtual Desktop until
  633.                                            the hotkeyed window's vertiacal position comes
  634.                                            onto the Desktop */
  635.         while(HotKeyWindow.y>(VirtualDesktopPos.y+HookParameters.SlidingYFactor))
  636.             {                           /* Move physical Desktop up one additional unit,
  637.                                            can also be seen to move all windows in virtual
  638.                                            Desktop down one additional unit */
  639.             lSlidingYFactor-=HookParameters.SlidingYFactor;
  640.             VirtualDesktopPos.y+=HookParameters.SlidingYFactor;
  641.             lDiff=VirtualDesktopPos.y-HookParameters.VirtualDesktopMax.y;
  642.             if(lDiff>0)                 /* Correct if we moved out of the physical Desktop */
  643.                 {
  644.                 lSlidingYFactor+=lDiff;
  645.                 break;                  /* We can't move further */
  646.                 }
  647.             }
  648.                                         /* Do the same downwards */
  649.         while(HotKeyWindow.y<VirtualDesktopPos.y)
  650.             {                           /* Move physical Desktop down one additional unit */
  651.             lSlidingYFactor+=HookParameters.SlidingYFactor;
  652.             VirtualDesktopPos.y-=HookParameters.SlidingYFactor;
  653.             lDiff=VirtualDesktopPos.y-HookParameters.VirtualDesktopMin.y;
  654.             if(lDiff<0)                 /* Correct if we moved out of the physical Desktop */
  655.                 {
  656.                 lSlidingYFactor+=lDiff;
  657.                 break;                  /* We can't move further */
  658.                 }
  659.             }
  660.         if(lSlidingXFactor || lSlidingYFactor)
  661.                                         /* Now move the windows and activate window after move */
  662.             WinSendMsg(hwndThread, WM_DESKTOPMOVE, MPFROMLONG(lSlidingXFactor), MPFROMLONG(lSlidingYFactor));
  663.                                         /* Get flags WinSetWindowPos() */
  664.         usfl=(Windows.wdWindow[ulWindowIndex].SwpFlag & ~SWP_NOMOVE) | SWP_SHOW;
  665.                                         /* If not switch handle found activate window through
  666.                                            WinSetWindowPos() else via WinSwitchToProgram which
  667.                                            also switches to different screen groups */
  668.         if(!Windows.wdWindow[ulWindowIndex].hswitchWindow)
  669.             usfl|=(SWP_ACTIVATE | SWP_ZORDER);
  670.         WinSetWindowPos(Windows.wdWindow[ulWindowIndex].swpWindow.hwnd,
  671.             HWND_TOP, 0, 0, 0, 0, usfl);
  672.         if(Windows.wdWindow[ulWindowIndex].hswitchWindow)
  673.             WinSwitchToProgram(Windows.wdWindow[ulWindowIndex].hswitchWindow);
  674.         }
  675.     else
  676.         {                               /* If no session found for the pressed hotkey, start
  677.                                            the corresponding session */
  678.         WinPostMsg(hwndClient, WM_COMMAND,
  679.                                         /* Get ID and set it as posted by a menu control */
  680.             MPFROM2SHORT((USHORT)(KeyData[ulKeyDataIndex].pMenuData->id), CMDSRC_MENU),
  681.                                         /* Simulate Message a result of a keyboard operation */
  682.             MPFROMCHAR(FALSE));
  683.         }
  684.     }
  685.     break;
  686.  
  687. /*                                                                                      *\
  688.  * Syntax: WM_WINDOWLIST, (USHORT x, USHORT y), NULL                                    *
  689. \*                                                                                      */
  690. case WM_WINDOWLIST:
  691. /*                                                                                      *\
  692.  * WM_WINDIWLIST is sent by PC2Hook.dll and passed from PC/2's window procedure, if     *
  693.  * mouse clicks are detected on PM that would display the Window List on the WPS. Be-   *
  694.  * cause the WPS displayed the Window List but not PM, we simulate this on PM.          *
  695.  * Ref.:                                                                                *
  696.  *          Windows ........... WINDOWS structure containing all windows control data   *
  697. \*                                                                                      */
  698.     {                                   /* Mouse position when Window List was requested */
  699.     USHORT      usX=SHORT1FROMMP(mp1), usY=SHORT2FROMMP(mp1);
  700.  
  701.     if(Windows.ulWindowList!=(ULONG)-1) /* Display Window List */
  702.         {
  703.                                         /* Place Window List centered under mouse pointer
  704.                                            whenever possible */
  705.         if((Windows.wdWindow[Windows.ulWindowList].swpWindow.cx>>1)>usX)
  706.             usX=0;
  707.         else if(HookParameters.DesktopSize.x-(Windows.wdWindow[Windows.ulWindowList].swpWindow.cx>>1)<usX)
  708.             usX=HookParameters.DesktopSize.x-Windows.wdWindow[Windows.ulWindowList].swpWindow.cx;
  709.         else usX=usX-(Windows.wdWindow[Windows.ulWindowList].swpWindow.cx>>1);
  710.         if((Windows.wdWindow[Windows.ulWindowList].swpWindow.cy>>1)>usY)
  711.             usY=0;
  712.         else if(HookParameters.DesktopSize.y-(Windows.wdWindow[Windows.ulWindowList].swpWindow.cy>>1)<usY)
  713.             usY=HookParameters.DesktopSize.y-Windows.wdWindow[Windows.ulWindowList].swpWindow.cy;
  714.         else usY=usY-(Windows.wdWindow[Windows.ulWindowList].swpWindow.cy>>1);
  715.         WinSetWindowPos(Windows.wdWindow[Windows.ulWindowList].swpWindow.hwnd,
  716.             HWND_TOP, usX, usY, 0, 0,
  717.             SWP_ZORDER | SWP_MOVE | SWP_SHOW | SWP_ACTIVATE | SWP_NOADJUST);
  718.         }
  719.     }
  720.     break;
  721.  
  722. /*                                                                                      *\
  723.  * Syntax: WM_MOVEREQUEST, (USHORT usMouseXPos, USHORT usMouseYPos), (ULONG ulMoveFlag) *
  724. \*                                                                                      */
  725. case WM_MOVEREQUEST:
  726. /*                                                                                      *\
  727.  * This local procedure is called from the PC2DLL_Hook procedure to move the windows    *
  728.  * within the virtual Desktop on its behalf.                                            *
  729.  * Req:                                                                                 *
  730.  *      usMouseXPos.... X Position of mouse pointer during creation of move message     *
  731.  *      usMouseYPos.... Y Position of mouse pointer during creation of move message     *
  732.  *      ulMoveFlag..... Bitmapped flag to control move                                  *
  733.  * Returns:                                                                             *
  734.  *      none                                                                            *
  735.  * Ref.:                                                                                *
  736.  *          Windows ........... WINDOWS structure containing all windows control data   *
  737. \*                                                                                      */
  738.     {
  739.                                         /* Get pointer position */
  740.     LONG        lMouseXPos=(LONG)SHORT1FROMMP(mp1);
  741.     LONG        lMouseYPos=(LONG)SHORT2FROMMP(mp1);
  742.     POINTL      VirtualDesktopPos;      /* Copy structure from HookParameters */
  743.                                         /* Get bitmapped move control flag */
  744.     ULONG       ulMoveFlag=LONGFROMMP(mp2);
  745.     LONG        lSlidingXFactor;        /* Horizontal offset to move */
  746.     LONG        lSlidingYFactor;        /* Vertical offset to move */
  747.     LONG        lDiff;                  /* Difference between movement and Desktop size */
  748.  
  749.     lSlidingXFactor=0;
  750.     lSlidingYFactor=0;
  751.     VirtualDesktopPos=HookParameters.VirtualDesktopPos;
  752.     if((ulMoveFlag&MOVEXR))
  753.         {                               /* Move physical Desktop left, but not over the
  754.                                            left border of the virtual Desktop */
  755.         lSlidingXFactor=HookParameters.SlidingXFactor;
  756.         VirtualDesktopPos.x-=HookParameters.SlidingXFactor;
  757.         lDiff=VirtualDesktopPos.x-HookParameters.VirtualDesktopMin.x;
  758.         if(lDiff<0)
  759.             {
  760.             lSlidingXFactor+=lDiff;
  761.             }
  762.         }
  763.     if((ulMoveFlag&MOVEXL))
  764.         {                               /* Move physical Desktop right, but not over the
  765.                                            right border of the virtual Desktop */
  766.         lSlidingXFactor=-HookParameters.SlidingXFactor;
  767.         VirtualDesktopPos.x+=HookParameters.SlidingXFactor;
  768.         lDiff=VirtualDesktopPos.x-HookParameters.VirtualDesktopMax.x;
  769.         if(lDiff>0)
  770.             {
  771.             lSlidingXFactor+=lDiff;
  772.             }
  773.         }
  774.     if((ulMoveFlag&MOVEYU))
  775.         {                               /* Move physical Desktop down, but not under the
  776.                                            bottom border of the virtual Desktop */
  777.         lSlidingYFactor=HookParameters.SlidingYFactor;
  778.         VirtualDesktopPos.y-=HookParameters.SlidingYFactor;
  779.         lDiff=VirtualDesktopPos.y-HookParameters.VirtualDesktopMin.y;
  780.         if(lDiff<0)
  781.             {
  782.             lSlidingYFactor+=lDiff;
  783.             }
  784.         }
  785.     if((ulMoveFlag&MOVEYD))
  786.         {                               /* Move physical Desktop up, but not over the
  787.                                            top border of the virtual Desktop */
  788.         lSlidingYFactor=-HookParameters.SlidingYFactor;
  789.         VirtualDesktopPos.y+=HookParameters.SlidingYFactor;
  790.         lDiff=VirtualDesktopPos.y-HookParameters.VirtualDesktopMax.y;
  791.         if(lDiff>0)
  792.             {
  793.             lSlidingYFactor+=lDiff;
  794.             }
  795.         }
  796.                                         /* If there is nothing to move, because we are
  797.                                            on a border position, don't do further processing
  798.                                            but return */
  799.     if(!lSlidingXFactor && !lSlidingYFactor) break;
  800.                                         /* Move pointer so that it is on that pixel it
  801.                                            would be, if we hadn't moved the windows. Also
  802.                                            change the pixel which gets the message. */
  803.     if(HookParameters.ulScrollPercentage==100)
  804.         WinSetPointerPos(HWND_DESKTOP, (lMouseXPos+=lSlidingXFactor*0.5),
  805.             (lMouseYPos+=lSlidingYFactor*0.5));
  806.     else
  807.         WinSetPointerPos(HWND_DESKTOP, (lMouseXPos+=lSlidingXFactor),
  808.             (lMouseYPos+=lSlidingYFactor));
  809.                                         /* Inform working thread to move windows */
  810.     WinPostMsg(HookParameters.hwndPC2, WM_DESKTOPMOVE,
  811.         MPFROMLONG(lSlidingXFactor), MPFROMLONG(lSlidingYFactor));
  812.     }
  813.     break;
  814.  
  815. default:                                /* Default window procedure must be called */
  816.     return((MRESULT)WinDefWindowProc(hwnd, msg, mp1, mp2));
  817. }
  818. return((MRESULT)FALSE);                 /* We have handled the message */
  819. }
  820.  
  821.